package com.salt.security.resource;

import com.salt.common.BusinessException;
import com.salt.common.ResponseStatus;
import com.salt.common.RestResponse;
import com.salt.security.UserDetailsServiceImpl;
import com.salt.security.jwt.JwtUtil;
import com.salt.security.model.request.LoginRequest;
import com.salt.security.model.request.WeChatLoginRequest;
import com.salt.security.model.respond.LoginRespond;
import com.salt.security.model.respond.WeChatNoBindRespond;
import com.salt.security.wechat.auth.JsCodeAuthenticationToken;
import com.salt.security.wechat.auth.WeChatPasswordAuthenticationToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 用户登录认证资源
 *
 * @author HaiBo Kuang
 * @date 2021/4/17 20:52
 */
@RestController
@RequestMapping("auth")
public class UserAuthResource {
    private final Logger logger = LoggerFactory.getLogger("User_Auth_Resource");
    private AuthenticationManager authenticationManager;
    private UserDetailsService userDetailsService;
    private JwtUtil jwtUtil;

    @Autowired
    public void setUserAuthResource(AuthenticationManager authenticationManager,
                                    UserDetailsServiceImpl userDetailsService,
                                    JwtUtil jwtUtil) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtUtil = jwtUtil;
    }

    /**
     * 用户登录请求
     *
     * @return 返回jwt
     */
    @PostMapping("login")
    public ResponseEntity<?> login(@RequestBody @Validated LoginRequest request) {
        try {
            authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(),
                            request.getPwd()));
        } catch (AuthenticationException e) {
            throw new BusinessException(ResponseStatus.USERNAME_PASSWORD_INCORRECT);
        }
        final UserDetails userDetails
                = userDetailsService.loadUserByUsername(request.getUsername());
        String jwt = jwtUtil.generateToken(userDetails);
        return ResponseEntity.ok(new LoginRespond(jwt));
    }

    /**
     * 用户微信jsCode登录
     *
     * @return 结果
     */
    @PostMapping("jsCodeLogin")
    public ResponseEntity<?> jsCodeLogin() {
        JsCodeAuthenticationToken jsCodeToken;
        try {
            jsCodeToken = (JsCodeAuthenticationToken) authenticationManager.
                    authenticate(new JsCodeAuthenticationToken("jsCode"));
        } catch (AuthenticationException e) {
            throw new BusinessException(ResponseStatus.WE_CHAT_SECRET_FREE_LOGIN_FAIL);
        }
        if (!jsCodeToken.getWeChatBind()) {
            // 用户未绑定
            return RestResponse.fail(ResponseStatus.WE_CHAT_NO_BIND, new WeChatNoBindRespond(jsCodeToken.getOpenId()));
        }
        String jwt = jwtUtil.generateToken(jsCodeToken.getUserDetails());
        return RestResponse.success(new LoginRespond(jwt));
    }

    /**
     * 微信登录
     *
     * @param request 登录请求
     * @return 结果
     */
    @PostMapping("we_chat/login")
    public ResponseEntity<?> weChatLogin(@RequestBody @Validated WeChatLoginRequest request) {
        try {
            authenticationManager.authenticate
                    (new WeChatPasswordAuthenticationToken(request.getUserNameOrPhone(),
                            request.getPwd(), request.getOpenId()));
        } catch (AuthenticationException e) {
            throw new BusinessException(ResponseStatus.USERNAME_PASSWORD_INCORRECT);
        }
        final UserDetails userDetails
                = userDetailsService.loadUserByUsername(request.getUserNameOrPhone());
        String jwt = jwtUtil.generateToken(userDetails);
        return ResponseEntity.ok(new LoginRespond(jwt));
    }

}
